package com.hevs.samplewebapp.client.screens;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.validation.ValidationException;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.Resources;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.hevs.samplewebapp.client.bean.Category;
import com.hevs.samplewebapp.client.bean.CompositeWRefresh;
import com.hevs.samplewebapp.client.dialogbox.ConfirmDialogBox;
import com.hevs.samplewebapp.client.bean.FieldVerifier;
import com.hevs.samplewebapp.client.bean.MedicalDataItem;
import com.hevs.samplewebapp.client.bean.Type;
import com.hevs.samplewebapp.client.bean.User;
import com.hevs.samplewebapp.client.services.PatientManagementServiceImpl;

/**
 * This is the Patient Management Tab
 * <p>The Goal of this tab is to provide a GUI to manage data from all the patients,
 * that the doctor is allowed to see.</p>  
 * @author: Matthias Hurni
 * @Date: 26.03.2012
 */
public class ManagePatientsWidget extends CompositeWRefresh
{
	// ------------------------------------------------------------
	// Variables
	// ------------------------------------------------------------
	
	// Layout
	/**
	 * Horizontal panel contains the widget
	 */
	private HorizontalPanel mainPanel=new HorizontalPanel();
	
	/**
	 * Vertical panel contains the patients data
	 */
	private VerticalPanel vPanelAdmin=new VerticalPanel();
	
	/**
	 * Flexpanel contains the buttons to add, update or delete a medical data
	 */
	private FlexTable hPanel=new FlexTable();

	/**
	 * Textbox with the value of the selected medical data
	 */
	private TextBox value =new TextBox();
	
	/**
	 * Listbox with the category of the selected medical data
	 */
	private ListBox category=new ListBox();
	
	/**
	 * Listbox with the type of the selected medical data
	 */
	private ListBox type=new ListBox();
	
	/**
	 * DateBox with the date of the selected medical data
	 */
	private DateBox date=new DateBox();
	
	/**
	 * Date formater
	 */
	private DateTimeFormat dateFormat=DateTimeFormat.getFormat("dd.MM.yyyy"); // Default date format

	/**
	 * Button to create a new medical data
	 */
	private Button create=new Button("Add");
	
	/**
	 * Button to delete a medical data
	 */
	private Button delete=new Button("Delete");
	
	/**
	 * Button to update a medical data
	 */
	private Button update=new Button("Update");

	/**
	 * List of granted patients for the celltable 
	 */
	private ListDataProvider<User> patientDataProvider;
	
	/**
	 * List of granted patients
	 */
	private List<User> patients;
	
	/**
	 * Celltable with the list of granted patients
	 */
	private CellTable<User> patientsTable;
	
	/**
	 * Column with the patients firstname
	 */
	private TextColumn<User> firstNameColumn;
	
	/**
	 * Column with the patients lastname
	 */
	private TextColumn<User> lastNameColumn;
	
	/**
	 * Handler to sort the patients by firstname 
	 */
	private ListHandler<User> firstNameSortHandler;
	
	/**
	 * Handler to sort the patients by lastname
	 */
	private ListHandler<User> lastNameSortHandler;
	
	/**
	 * Pager to go trought the list of patients when they are above 15
	 */
	private SimplePager patientsPager;

	/**
	 * List of medical data for the Celltable for a selected patient
	 */
	private ListDataProvider<MedicalDataItem> medDatDataProvider;
	
	/**
	 * List of medical data for a selected patient
	 */
	private List<MedicalDataItem> medDats;
	
	/**
	 * Celltable with the list of medical data from a selected patient in it
	 */
	private CellTable<MedicalDataItem> medDatsTable;
	
	/**
	 * Column with the medical data type
	 */
	private TextColumn<MedicalDataItem> typeColumn;
	
	/**
	 * Column with the medical data value
	 */
	private TextColumn<MedicalDataItem> valueColumn;
	
	/**
	 * Column with the medical data date
	 */
	private TextColumn<MedicalDataItem> dateColumn;
	
	/**
	 * Handler to sort medical data by date
	 */
	private ListHandler<MedicalDataItem> dateSortHandler;
	
	/**
	 * Pager to go trought the list of medical data when they are above 15
	 */
	private SimplePager medDatsPager;

	/**
	 * ClientBundle that provides pager images for this widget   
	 */
	private Resources resources=GWT.create(SimplePager.Resources.class);
	
	/**
	 * The selected patient
	 */
	private User currentEditedPatient;
	
	/**
	 * the selected Medical data
	 */
	private MedicalDataItem currentEditedData;
	
	/**
	 * List of patient from the web service
	 */
	private List<User> patientListRest;
	
	/**
	 * List of medical data from the web service
	 */
	private List<MedicalDataItem> medDatListRest;
	
	/**
	 * Initialization of the web service for doctor patients data management 
	 */
	private static PatientManagementServiceImpl patientService = new PatientManagementServiceImpl(); // Rest service

	// ----------------------------------------------------------------------------
	// CONSTRUCTOR
	// ----------------------------------------------------------------------------
	/**
	 * Constructor of the Manage patients widget
	 */
	public ManagePatientsWidget()
	{
		// ------------------------------------------------------------------------
		// Layout description
		// ------------------------------------------------------------------------

		setButtonListeners();
		mainPanel.setSpacing(8);
		mainPanel.add(patientList());
		mainPanel.add(medDatsList());
		mainPanel.add(medDatsForm());

		// ------------------------------------------------------------------------
		// Widget initialization
		// ------------------------------------------------------------------------
		
		refreshPatientCellTable();
		initWidget(mainPanel);
	}

	// ------------------------------------------------------------------------
	// Public Methods
	// ------------------------------------------------------------------------

	/**
	 * Refresh the patients' cell table
	 */
	public void refreshPatientCellTable()
	{
		// Rest call to get a list of patients
		patientsTable.setRowCount(0);
		patientListRest=getPatientList();
		
		setPatientListListeners();
		patientsTable.setRowCount(patientListRest.size(),true);
		
		// Reset current user
		currentEditedPatient=null;
	}

	@Override
	/**
	 * Method for fake sync call
	 */
	public void refreshComp()
	{
		setMedDatListData(1);
	}
	
	/**
	 * Clear table
	 */
	public void clearMedTable()
	{
		medDatsTable.setRowCount(0);
	}
	
	// ------------------------------------------------------------------------
	// Private Methods
	// ------------------------------------------------------------------------	
	
	/**
	 * Create the medical data details form
	 * @return
	 * the widget for detailed view of a medical record
	 */
	private Widget medDatsForm()
	{
		// Layout
		FlexTable layout=new FlexTable();
		layout.setCellSpacing(6);
		FlexCellFormatter cellFormatter=layout.getFlexCellFormatter();

		// Fill the ListBoxes with defined Types and Categories
		for(int i=0;i<Category.getSize();i++)
		{
			Category temp=Category.get(i);
			category.addItem(temp.getName(),String.valueOf(temp.getLevel()));
		}
		for(int i=0;i<Type.getSize();i++)
		{
			Type temp=Type.getFromInt(i);
			type.addItem(temp.getName(),String.valueOf(temp.getLevel()));
		}
			
		// Prepare DateBox
		date.setFormat(new DateBox.DefaultFormat(dateFormat));
		date.setValue(new Date());
		date.getDatePicker().setCurrentMonth(date.getValue());
		
		// Additional form properties
		layout.setHTML(0,0,"Patient details");
		cellFormatter.setColSpan(0,0,2);
		cellFormatter.setHorizontalAlignment(0,0,HasHorizontalAlignment.ALIGN_CENTER);

		// Put the form in the layout
		layout.setHTML(1,0,"Value:");
		layout.setWidget(1,1,value);
		layout.setHTML(2,0,"Date:");
		layout.setWidget(2,1,date);
		layout.setHTML(3,0,"Category:");
		layout.setWidget(3,1,category);
		layout.setHTML(4,0,"Type:");
		layout.setWidget(4,1,type);

		// Prepare buttons for administration options
		hPanel.setWidget(0,1,create);
		hPanel.setWidget(0,2,update);
		hPanel.setWidget(0,3,delete);

		create.setWidth("100%");
		update.setWidth("100%");
		delete.setWidth("100%");

		hPanel.setWidth("100%");

		// Wrap the content in a DecoratorPanel
		vPanelAdmin.add(layout);
		vPanelAdmin.add(hPanel);

		DecoratorPanel decPanel=new DecoratorPanel();
		decPanel.setWidget(vPanelAdmin);

		return decPanel;
	}

	/**
	 * Create the cell table for patients
	 * @return
	 * the widget with the granted patients list
	 */
	private Widget patientList()
	{
		VerticalPanel vPanel=new VerticalPanel();
		
		patientsTable=new CellTable<User>();
		patientListRest=new ArrayList<User>();

		// ------------------------------------------------------------------------
		// Cell table with patients' names
		// ------------------------------------------------------------------------

		// Get the list of patients into the table content provider
		patientDataProvider=new ListDataProvider<User>();
		
		// Create the pager for the table
	    patientsPager=new SimplePager(TextLocation.CENTER,resources,false,1000,true);
	    patientsPager.setDisplay(patientsTable);
	    patientsPager.setPageSize(10);

		// Rest call to get a list of patients
		patientListRest=getPatientList();

		// Create the first name header of column
		firstNameColumn=new TextColumn<User>()
		{
			@Override
			public String getValue(User user)
			{
				return user.getFirstName();
			}
		};

		// Create the last name header of column
		lastNameColumn=new TextColumn<User>()
		{
			@Override
			public String getValue(User user)
			{
				return user.getLastName();
			}
		};

		// Make the relevant columns sortable (all in this case)
		firstNameColumn.setSortable(true);
		lastNameColumn.setSortable(true);

		// Add the columns to the cell table
		patientsTable.addColumn(firstNameColumn,"First name");
		patientsTable.addColumn(lastNameColumn,"Last name");

		// Set columns sizes
		patientsTable.setColumnWidth(firstNameColumn,25.0,Unit.PCT);
		patientsTable.setColumnWidth(lastNameColumn,25.0,Unit.PCT);
		
		// Add a selection model to handle user selection
		final SingleSelectionModel<User> selectionModel=new SingleSelectionModel<User>();
		patientsTable.setSelectionModel(selectionModel);
		selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
		{
			public void onSelectionChange(SelectionChangeEvent event)
			{
				User selected=selectionModel.getSelectedObject();
				if(selected!=null)
				{
					// Set right information in box
					currentEditedPatient=selected;

					// Refresh the list with server sync
					setMedDatListData(0);
					
					// Clear form fields
					clearFields();
				}
			}
		});

		// Set content of the table from the patients in the list
		patientDataProvider.addDataDisplay(patientsTable);
		
		vPanel.add(patientsTable);
		vPanel.add(patientsPager);
		vPanel.setCellHorizontalAlignment(patientsPager,VerticalPanel.ALIGN_CENTER);
		
		return vPanel;
	}

	/**
	 * Create the cell table for a patients' medical data
	 * @return
	 * the widget with the list of medical data for the selected patient
	 */
	private Widget medDatsList()
	{
		VerticalPanel vPanel=new VerticalPanel();
		
		medDatsTable=new CellTable<MedicalDataItem>();

		// ------------------------------------------------------------------------
		// Cell table with medical Data from the current User
		// ------------------------------------------------------------------------

		// Get the list of medical data into the table content provider
		medDatDataProvider=new ListDataProvider<MedicalDataItem>();
		
		// Create the pager for the table
	    medDatsPager=new SimplePager(TextLocation.CENTER,resources,false,1000,true);
	    medDatsPager.setDisplay(medDatsTable);
	    medDatsPager.setPageSize(10);

		// Create type header of column
		typeColumn=new TextColumn<MedicalDataItem>()
		{
			@Override
			public String getValue(MedicalDataItem medDat)
			{
				return Type.getFromVal(medDat.getType()).getName();
			}
		};

		// Create value header of column
		valueColumn=new TextColumn<MedicalDataItem>()
		{
			@Override
			public String getValue(MedicalDataItem medDat)
			{
				return String.valueOf(medDat.getValue());
			}
		};

		// Create date header of column
		dateColumn=new TextColumn<MedicalDataItem>()
		{
			@Override
			public String getValue(MedicalDataItem medDat)
			{
				return medDat.getDate();
			}
		};

		// Make the relevant columns sortable
		dateColumn.setSortable(true);

		// Add the columns to the cell table
		medDatsTable.addColumn(typeColumn,"Type");
		medDatsTable.addColumn(valueColumn,"Value");
		medDatsTable.addColumn(dateColumn,"Date");

		// Set columns sizes
		medDatsTable.setColumnWidth(typeColumn,25.0,Unit.PCT);
		medDatsTable.setColumnWidth(valueColumn,25.0,Unit.PCT);
		medDatsTable.setColumnWidth(dateColumn,25.0,Unit.PCT);

		// Set content of the table from the data in the list
		medDatDataProvider.addDataDisplay(medDatsTable);

		// Add a selection model to handle data selection
		final SingleSelectionModel<MedicalDataItem> selectionModel=new SingleSelectionModel<MedicalDataItem>();
		medDatsTable.setSelectionModel(selectionModel);
		selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
		{
			public void onSelectionChange(SelectionChangeEvent event)
			{
				MedicalDataItem selected=selectionModel.getSelectedObject();
				if(selected!=null)
				{
					currentEditedData=selected;
					value.setText(String.valueOf(selected.getValue()));
					date.setValue(dateFormat.parse(selected.getDate()));
					date.getDatePicker().setCurrentMonth(date.getValue());
					category.setSelectedIndex(selected.getCategory());
					type.setSelectedIndex(Type.getIndex(selected.getType()));
				}
			}
		});
		
		vPanel.add(medDatsTable);
		vPanel.add(medDatsPager);
		vPanel.setCellHorizontalAlignment(medDatsPager,VerticalPanel.ALIGN_CENTER);

		return vPanel;
	}
	
	/**
	 * Get the patient list from server
	 * @return
	 * the list of granted patient for this doctor
	 */
	private List<User> getPatientList()
	{
		patientService.getPatients();
		return patientService.getPatientList();
	}
	
	/**
	 * Get the patients' medical data list from server
	 * @return
	 * the list of medical data for the selected user
	 */
	private List<MedicalDataItem> getMedDatList()
	{
		patientService.getMedDats(currentEditedPatient.getEmail(), this);
		return patientService.getMedDatList();
	}
	
	/**
	 * Set content of the table from the data into the list
	 * @param refreshGrade
	 */
	private void setMedDatListData(int refreshGrade)
	{
		switch(refreshGrade)
		{
			// Refresh with server call
			case 0:
				medDatListRest=new ArrayList<MedicalDataItem>();
		
				// Rest call to get a list of patients
				medDatListRest=getMedDatList();
		
				// Add the data to the data provider (filling the GUI table)
				medDats=medDatDataProvider.getList();
				medDats.clear();
				
				for(MedicalDataItem data:medDatListRest)
					medDats.add(data);
				break;
			// Simple table refresh (cause of async server call)
			case 1:
				medDatListRest=new ArrayList<MedicalDataItem>();
				
				// Get temp list from Service
				medDatListRest=patientService.getMedDatList();
				
				// Add the data to the data provider (filling the GUI table)
				medDats=medDatDataProvider.getList();
				medDats.clear();
				
				for(MedicalDataItem data:medDatListRest)
					medDats.add(data);
				break;
			default:
				break;
		}
		setMedDatsSortListener(medDats);

		medDatsTable.setRowCount(medDatListRest.size(),true);
		
		// Reset current medical data
		currentEditedData=null;
	}
	
	/**
	 * Clear the form fields
	 */
	private void clearFields()
	{
		value.setText(null);
		date.setValue(new Date());
		date.getDatePicker().setCurrentMonth(date.getValue());
		category.setSelectedIndex(-1);
		type.setSelectedIndex(-1);
	}
	
	/**
	 * Method to verify the fields
	 * @param type
	 * the type of medical data
	 * @param category
	 * the category of medical data
	 * @param field
	 * 
	 */
	private void verifyFields(ListBox type,ListBox category,TextBox field)
	{
		Type temp=Type.getFromInt(type.getSelectedIndex());
		switch (temp)
		{
			case BLOODSUGAR:
				FieldVerifier.validateCategory(temp.getName(),field,category);
				FieldVerifier.validateAndParseDouble(temp.getName(),field,0.,200.);
				break;
			case HUMALOG: case NOVORAPID:
				FieldVerifier.validateCategory(temp.getName(),field,category);
				FieldVerifier.validateAndParseInt(temp.getName(),field,0,100);
				break;
			case WEIGHT:
				FieldVerifier.validateAndParseDouble(temp.getName(),field,0.,400.);
				break;
			case DIASTOLIC:
				FieldVerifier.validateAndParseDouble(temp.getName(),field,0.,300.);
				break;
			case SYSTOLIC:
				FieldVerifier.validateAndParseDouble(temp.getName(),field,0.,300.);
				break;
			case PULSERATE:
				FieldVerifier.validateAndParseInt(temp.getName(),field,1,300);
				break;
			default:
				throw new ValidationException("Not a valid type!");
		}
	}
	
	// ------------------------------------------------------------------------
	// PopUp's
	// ------------------------------------------------------------------------

	/**
	 * Pop up to create a medical data set
	 */
	private void askingCreate()
	{
		//check if a patient is selected
		if(currentEditedPatient!=null){
		final DialogBox box=new DialogBox();
		box.setGlassEnabled(true);
		box.setAnimationEnabled(true);
		box.setText("Create a new medical data");
		
		// Create a table to layout the content
		VerticalPanel mainLayout=new VerticalPanel();
		HorizontalPanel buttonLayout=new HorizontalPanel();
		
		Button create=new Button("Create");
		Button cancel=new Button("Cancel");
		final TextBox value=new TextBox();
		final DateBox date=new DateBox();
		final ListBox category=new ListBox();
		final ListBox type=new ListBox();
		
		date.setFormat(new DateBox.DefaultFormat(dateFormat));
		date.setValue(new Date());
		date.getDatePicker().setCurrentMonth(date.getValue());
		
		// Fill the ListBoxes with defined Types and Categories
		for(int i=0;i<Category.getSize();i++)
		{
			Category temp=Category.get(i);
			category.addItem(temp.getName(),String.valueOf(temp.getLevel()));
		}
		for(int i=0;i<Type.getSize();i++)
		{
			Type temp=Type.getFromInt(i);
			type.addItem(temp.getName(),String.valueOf(temp.getLevel()));
		}
		
		FlexTable input=new FlexTable();
		input.setHTML(1,0,"Value:");
		input.setWidget(1,1,value);
		input.setHTML(2,0,"Date:");
		input.setWidget(2,1,date);
		input.setHTML(3,0,"Category:");
		input.setWidget(3,1,category);
		input.setHTML(4,0,"Type:");
		input.setWidget(4,1,type);
		
		// Listeners
		create.addClickHandler(new ClickHandler()
		{
			@Override
			public void onClick(ClickEvent event)
			{
				// Send the newly created medical data
				JSONObject medDat=new JSONObject();
				try
				{
					verifyFields(type,category,value);
					medDat.put("value",new JSONNumber(Double.valueOf(value.getText())));
					medDat.put("date",new JSONString(dateFormat.format(date.getValue())));
					medDat.put("category",new JSONNumber(Integer.valueOf(category.getValue(category.getSelectedIndex()))));
					medDat.put("type",new JSONNumber(Integer.valueOf(type.getValue(type.getSelectedIndex()))));
					
					patientService.update(medDat, currentEditedPatient.getEmail(), ManagePatientsWidget.this);

					//refresh the list
					setMedDatListData(0);
					
					box.hide();
					Window.alert("New medical data created successfully");
				}
				catch(ValidationException e)
				{
					Window.alert(e.getMessage());
				}
				catch(JSONException e)
				{
					Window.alert("Failed to create a new medical data");
				}
			}
		});
		
		cancel.addClickHandler(new ClickHandler()
		{
			@Override
			public void onClick(ClickEvent event)
			{
				value.setText(null);
				date.setValue(new Date());
				date.getDatePicker().setCurrentMonth(date.getValue());
				category.setSelectedIndex(-1);
				type.setSelectedIndex(-1);
				box.hide();
			}
		});
		
		create.setWidth("100%");
		cancel.setWidth("100%");
		buttonLayout.add(create);
		buttonLayout.add(cancel);
		buttonLayout.setSpacing(10);
		
		mainLayout.add(input);
		mainLayout.add(buttonLayout);
		mainLayout.setSpacing(5);
		mainLayout.setCellHorizontalAlignment(buttonLayout,VerticalPanel.ALIGN_CENTER);
		
		box.setWidget(mainLayout);
		box.show();
		box.center();
		}else
			Window.alert("Please select a patient!");
	}
	
	/**
	 * Pop up confirm delete a medical data
	 * @param medDat
	 * the medical data to delete
	 */
	private void askingDelete(final MedicalDataItem medDat)
	{
		String title="Deleting a medical data";
		String[] messages={"You are about to delete this medical data, are you sure?"};
		//check if an item is selected
		if(currentEditedData!=null){
	
		final ConfirmDialogBox box=new ConfirmDialogBox(title,messages);
		
		box.show();
		box.center();
		box.addCloseHandler(new CloseHandler<PopupPanel>()
				{
					@Override
					public void onClose(CloseEvent<PopupPanel> event)
					{
						if(box.getChoice()==ConfirmDialogBox.YES)
						{
							JSONObject medDatJSON=new JSONObject();
							try
							{
								medDatJSON.put("key",new JSONString(medDat.getId()));
								patientService.delete(medDatJSON, currentEditedPatient.getEmail(), ManagePatientsWidget.this);
								
								// Refresh the list
								setMedDatListData(0);
							}
							catch(Exception e)
							{
								Window.alert("failed to delete current user");
							}
						}
					}
				});
		}else
			Window.alert("Please select a medical record!");
	}
	
	/**
	 * Pop up to confirm the medical data update
	 * @param medDat
	 * the medical data to update
	 */
	private void askingUpdate(final MedicalDataItem medDat)
	{
		String title="Update medical data";
		String[] messages={"You are about to update the medical data, are you sure?"};
		//check if any item is selected
		if(currentEditedData!=null){
			
		final ConfirmDialogBox box=new ConfirmDialogBox(title,messages);
		
		box.show();
		box.center();
		box.addCloseHandler(new CloseHandler<PopupPanel>()
				{
					@Override
					public void onClose(CloseEvent<PopupPanel> event)
					{
						if(box.getChoice()==ConfirmDialogBox.YES)
						{
							try
							{
								verifyFields(type,category,value);
								JSONObject medDatJSON=new JSONObject();
								medDatJSON.put("key",new JSONString(medDat.getId()));
								medDatJSON.put("value",new JSONNumber(Double.valueOf(value.getText())));
								medDatJSON.put("date",new JSONString(medDat.getDate()));
								medDatJSON.put("category",new JSONNumber(medDat.getCategory()));
								medDatJSON.put("type",new JSONNumber(medDat.getType()));
								patientService.update(medDatJSON, currentEditedPatient.getEmail(), ManagePatientsWidget.this);
								
								// Refresh the list
								setMedDatListData(0);
								
								Window.alert("Medical data updated");
							}
							catch(ValidationException e)
							{
								Window.alert(e.getMessage());
							}
							catch(Exception e)
							{
								Window.alert("Failed to update the medical data");
								e.printStackTrace();
							}
						}
					}					
				});
		}else
			Window.alert("Please select a medical record!");
	}
	
	// ------------------------------------------------------------------------
	// Listeners methods
	// ------------------------------------------------------------------------

	/**
	 * Button listeners for create, delete and update
	 */
	private void setButtonListeners()
	{
		ManagePatientsHandler handler=new ManagePatientsHandler();
		create.addClickHandler(handler);
		delete.addClickHandler(handler);
		update.addClickHandler(handler);
	}
	
	/**
	 * Common method to update the cell table completely
	 */
	private void setPatientListListeners()
	{
		// Add the patients to the data provider (filling the GUI table)
		patients=patientDataProvider.getList();
		patients.clear();
		for(User patient:patientListRest)
			patients.add(patient);

		// ------------------------------------------------------------------------
		// Cell table's columns sorters
		// ------------------------------------------------------------------------

		// First name sorter listener
		firstNameSortHandler=new ListHandler<User>(patients);
		firstNameSortHandler.setComparator(firstNameColumn,
				new Comparator<User>()
				{
					public int compare(User o1,User o2)
					{
						if(o1==o2)
							return 0;
		
						// Compare the name columns
						if(o1!=null)
							return (o2!=null)?o1.getFirstName().compareTo(o2.getFirstName()):1;
						return -1;
					}
				});

		// Last name sorter listener
		lastNameSortHandler=new ListHandler<User>(patients);
		lastNameSortHandler.setComparator(lastNameColumn,
				new Comparator<User>()
				{
					public int compare(User o1,User o2)
					{
						if(o1==o2)
							return 0;
		
						// Compare the name columns
						if(o1!=null)
							return (o2!=null)?o1.getLastName().compareTo(o2.getLastName()):1;
						return -1;
					}
				});

		patientsTable.addColumnSortHandler(firstNameSortHandler);
		patientsTable.addColumnSortHandler(lastNameSortHandler);

		// We know that the data is sorted alphabetically by default
		patientsTable.getColumnSortList().push(firstNameColumn);
		patientsTable.getColumnSortList().push(lastNameColumn);
	}
	
	/**
	 * Refresh the sort listeners for the table
	 * @param list
	 * Lsit of medical data to refresh
	 */
	private void setMedDatsSortListener(List<MedicalDataItem> list)
	{
		dateSortHandler=new ListHandler<MedicalDataItem>(list);
		dateSortHandler.setComparator(dateColumn,
				new Comparator<MedicalDataItem>()
				{
					public int compare(MedicalDataItem o1,MedicalDataItem o2)
					{
						Date d1;
						Date d2;
						
						if(o1==o2)
							return 0;
						
						d1=dateFormat.parse(o1.getDate());
						d2=dateFormat.parse(o2.getDate());
								
						// Compare the dates
						if(d1!=null)
							return (d2!=null)?d1.compareTo(d2):1;
						return -1;
					}
				});
		
		medDatsTable.addColumnSortHandler(dateSortHandler);
		
		medDatsTable.getColumnSortList().push(dateColumn);
	}

	/**
	 * Event handler for this screen
	 *<p>it provides the click handler for the buttons create, update and delete</p>
	 */
	private class ManagePatientsHandler implements ClickHandler
	{
		@Override
		public void onClick(ClickEvent event)
		{
			if(event.getSource()==create)
				askingCreate();
			if(event.getSource()==delete)
				askingDelete(currentEditedData);
			if(event.getSource()==update)
				askingUpdate(currentEditedData);
		}
	}

	// ------------------------------------------------------------------------
	// Getters / Setters
	// ------------------------------------------------------------------------

	/**
	 * Getter for the value textbox
	 * @return
	 * the value of the medical data in the textbox
	 */
	public TextBox getValue()
	{
		return value;
	}

	/**
	 * Setter for the value textbox
	 * @param value
	 * the value to display in the value textbox
	 */
	public void setValue(TextBox value)
	{
		this.value=value;
	}

	/**
	 * Getter for the date datebox
	 * @return
	 * the date of the medical data in the datebox
	 */
	public DateBox getDate()
	{
		return date;
	}

	/**
	 * Setter for the date datebox
	 * @param date
	 * the value to display in the datebox
	 */
	public void setDate(DateBox date)
	{
		this.date=date;
	}

	/**
	 * Getter for the category Listbox
	 * @return
	 * the category of the medical data selected in the Listbox
	 */
	public ListBox getCategory()
	{
		return category;
	}

	/**
	 * Setter for the category Listbox
	 * @param category
	 * the category to  display in the listbox
	 */
	public void setCategory(ListBox category)
	{
		this.category=category;
	}

	/**
	 * Getter for the type Listbox
	 * @return
	 * the type of medical data selected in the listbox
	 */
	public ListBox getType()
	{
		return type;
	}

	/**
	 * Setter for the type Listbox
	 * @param type
	 * the type to display in the listbox
	 */
	public void setType(ListBox type)
	{
		this.type=type;
	}
}